import datetime

from flask import current_app, g
from sqlalchemy import extract
from sqlalchemy.sql.functions import sum
from werkzeug.security import generate_password_hash, check_password_hash
import logging

from app.models.car import CarInfo
from app.models.parking_rate import ParkingRate
from app.models.road_toll import RoadToll
from app.models.ruel_cost import RuelCost
from common.utils.db import TotalNumberSerializer
from common.utils.db_tools import (
    get_car_mileage_date,
    get_car_cost_date,
    car_mileage_time_list,
    make_mileage_response,
    car_cost_list,
    make_cost_response,
)
from common.utils.jwt_util import create_token, check_token
from app import serializer
from marshmallow import (
    fields,
    Schema,
    validates,
    validates_schema,
    ValidationError,
    post_dump,
    post_load,
    pre_load,
)

from app.models import db
from app.models.user import User, Role, PermissionPath
from common.utils.tools import ImportFileTools

from app.models.collection import DataCollection

LOG = logging.getLogger(__name__)


class CarDataCostQuerySerializer(serializer.Schema):
    car_ids = fields.List(fields.Integer())
    year = fields.String()
    month = fields.String()
    day = fields.String()

    @pre_load
    def befor_action(self, data, many, *args, **kwargs):
        data_body = {}
        if data.get("car_ids"):
            data_body["car_ids"] = data.get("car_ids").split(",")
        if data.get("year"):
            data_body["year"] = data.get("year")
        if data.get("month"):
            data_body["month"] = data.get("month")
        if data.get("day"):
            data_body["day"] = data.get("day")

        return data_body

    @post_load
    def select(self, data, many, *args, **kwargs):
        response_body = {"data": [], "cost": [], "data_xAxis": [], "cost_xAxis": []}
        if not data.get("car_ids"):
            return response_body

        # 获取所有的车辆添加到body中
        cars = CarInfo.query.filter(CarInfo.id.in_(data.get("car_ids"))).all()

        if len(cars):
            cost_data_dict = {}
            li_data_dict = {}
            for car in cars:

                car_data = get_car_mileage_date(car)
                li_data_dict[car.car_num] = car_mileage_time_list(
                    car_data, response_body=response_body
                )
                car_ruel, car_road, car_parking = get_car_cost_date(car)
                cost_data_dict[car.car_num] = car_cost_list(
                    car_ruel, car_road, car_parking, response_body=response_body
                )

            # 生成里程数据
            make_mileage_response(li_data_dict=li_data_dict, response_body=response_body)
            make_cost_response(response_body=response_body, cost_data_dict=cost_data_dict)

        return response_body


class ImportFileQuerySerializer(serializer.Schema):
    file = fields.String()
    file_type = fields.String()

    @post_load
    def import_file(self, data, many, *args, **kwargs):
        import_tools = ImportFileTools()
        """将上传的文件保存到数据库"""
        file = self.context.get("request").files.get("file")

        file_type = data.get("file_type")

        if file_type == "ruel":
            # 燃油费表
            import_tools.ruel(file)
            pass
        elif file_type == "park":
            # 停车费表
            import_tools.parking(file)
            pass
        elif file_type == "load":

            # 过路费表
            import_tools.road(file)
            pass
        elif file_type == "collection":
            # 六路摄像头数据表
            import_tools.collection(file)
            pass
        elif file_type == "parking_collection":
            # 停车场数据表
            import_tools.parking_collection(file)
            pass

        return 200

        pass


class UserNumberSerializer(serializer.Schema):

    role_name = fields.String()
    count = fields.Integer()


class PermissionPathSonSerializer(serializer.Schema):

    id = fields.Integer()
    path = fields.String()
    path_name = fields.String()
    icon = fields.String()


class PermissionPathSerializer(serializer.Schema):

    id = fields.Integer()
    path = fields.String()
    path_name = fields.String()
    icon = fields.String()
    son = fields.Nested(PermissionPathSonSerializer(many=True))


class RoleBodySerializer(serializer.Schema):
    path = fields.Nested(PermissionPathSerializer(many=True))
    id = fields.Integer()
    role_name = fields.String()


class RoleBodyListSerializer(serializer.Schema):
    id = fields.Integer()
    role_name = fields.String()


class UserBodySerializer(serializer.SQLAlchemySchema):
    roles = fields.Nested(RoleBodySerializer())

    class Meta:
        model = User
        fields = ["id", "username", "roles", "super_user"]


class UserDataSerizlizer(serializer.SQLAlchemySchema, TotalNumberSerializer):
    data = fields.Nested(UserBodySerializer(many=True))


class UserInfoQuerySerializer(serializer.SQLAlchemySchema):
    page = fields.Integer()
    per_page = fields.Integer()

    class Meta:
        model = User
        fields = [
            "id",
        ]

    @validates_schema
    def validate_username(self, data, **kwargs):
        """
        验证用户并返回user_obj
        """
        pass

    @post_load(pass_many=True)
    def get_users(self, data, many, **kwargs):

        # users = db.session.query(User).filter_by(**data).paginate(page, per_page)
        data["deleted"] = False
        try:
            user = User.query.get(data.get("id"))
        except Exception as e:
            raise e
        return user


class UserListQuerySerializer(serializer.SQLAlchemySchema):
    page = fields.Integer()
    per_page = fields.Integer()

    class Meta:
        model = User
        fields = ["id", "page", "per_page"]

    @validates_schema
    def validate_username(self, data, **kwargs):
        """
        验证用户并返回user_obj
        """
        pass

    @post_load(pass_many=True)
    def get_users(self, data, many, **kwargs):

        # users = db.session.query(User).filter_by(**data).paginate(page, per_page)
        data["deleted"] = False
        try:
            user = (
                db.session.query(User)
                .filter_by(**data)
                .paginate(page=data.get("page"), per_page=data.get("per_page"))
            )
        except Exception as e:
            raise e
        return user.items, user.total


class UserTokenSerizlizer(Schema):
    username = fields.Str()
    token = fields.Str()


class UserLoginQuerySerizlizer(Schema):
    username = fields.Str(required=True)
    password = fields.Str(required=True)

    @validates_schema
    def validates_data(self, data, **kwargs):
        try:
            self.user = User.query.filter_by(username=data.get("username")).first()
        except Exception as e:
            raise ValueError("用户名或密码错误")
        if not check_password_hash(self.user.password, data.get("password")):
            raise ValueError("用户名密码错误")

    @post_load
    def get_token(self, data, many, **kwargs):
        # 生成token
        data["token"] = create_token({"user_id": self.user.id})
        return data


class UserRegistrationBodySerializer(Schema):
    id = fields.Int()


class UserRegistrationQuerySerializer(Schema):
    username = fields.Str(required=True)
    password = fields.Str(required=True)
    password2 = fields.Str(required=True)
    role = fields.Number(required=True)

    @validates_schema
    def validate(self, data, **kwargs):
        if data.get("password") != data.get("password2") or data.get("username") == -1:
            raise RecursionError

    @post_load
    def save(self, data, many, **kwargs):
        # 通过了验证进行密码加密
        data["password"] = generate_password_hash(data.get("password"))
        try:
            role = Role.query.get(data.get("role"))
        except Exception as e:
            raise e
        user = User(username=data.get("username"), password=data.get("password"), role_id=role.id)

        db.session.add(user)
        db.session.commit()

        return user


class UpdateFiles(Schema):
    # 列表中的文件字段用fields.Function
    file = fields.List(fields.Function)
    name = fields.String()

    @validates_schema
    def validate(self, data, **kwargs):
        print(data)
